package cn.edu.tju.wiki.normalization;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import cn.edu.tju.wiki.utils.Constant;
import cn.edu.tju.wiki.utils.GenJsonJsFile;

public class Dictionary {
	private static final double thresPrecise = 0.8;
	public static final String outPutPath = "/Users/liudajian/Documents/workshop/tomcat/webapps/CH/d3-pages/wikidata/data/hits.js";
	public static final String outPutHerPath = "/Users/liudajian/Documents/workshop/tomcat/webapps/CH/d3-pages/wikidata/data/keywords.json";
	public static final String outPutSunPath = "/Users/liudajian/Documents/workshop/tomcat/webapps/CH/d3-pages/wikidata/data/sunburst.json";
	public static final String outPutHeaPath = "/Users/liudajian/Documents/workshop/tomcat/webapps/CH/d3-pages/wikidata/data/heatMap.tsv";
	public static final String outPutHeaAxisPath = "/Users/liudajian/Documents/workshop/tomcat/webapps/CH/d3-pages/wikidata/scripts/heatMapAxis.js";
	public static final String outPutCoorPath = "/Users/liudajian/Documents/workshop/tomcat/webapps/CH/d3-pages/wikidata/data/miserables.json";
	public static final String[][] dictStr = {
			{ "單", "啈箙", "刀", "丩毌", "口", "子", "子刀系", "子單", "子天單", "子弓", "子正",
					"子媚", "子義", "子蝠", "子蝠何", "子龔", "弓", "尹舟", "及", "天", "夫冊",
					"弔", "戈", "戈北單冊冊", "爻", "犬", "兮建", "毌得", "毌侢", "木羊", "丙",
					"冊", "冊融", "冊亯", "北單", "史", "史寧", "寧", "寧戈", "寧戈冊", "寧劦",
					"交", "光", "夸", "字", "守", "宅止", "此", "羊", "羊箙", "羊京", "耒",
					"至", "耳", "耳髭", "臣辰冊", "臣辰", "屰", "舌", "西單", "戍尸", "串雞",
					"何", "克", "吳", "見", "車", "酉", "京", "并", "亞", "亞夫", "亞父",
					"亞舟", "亞址", "亞其", "亞長", "亞奚", "亞倗", "亞得", "亞鳥", "亞奠", "亞陲",
					"亞鼎", "亞酗", "亞屮", "亞盥", "亞貘", "其", "受", "武", "羍", "南單",
					"爰", "眉", "斿", "臤", "家戈", "息", "旅", "倗", "剢", "魚", "鳥",
					"貫", "得", "單", "象", "貯", "鄉寧", "聑", "歮", "鼎", "萬", "鼎劦",
					"箙", "箙戊", "鳶", "融", "藝", "龔子" }, {}, {}, {}, {} };

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		String source = "正月初吉丁亥工王皮之子者睪擇鐘不帛白不不濼不淍協于霝龠籥卑龢卑用祈眉壽釐于其皇且祖皇考若參壽卑女汝音音龢龢倉倉其登于上下聞于四旁方";
		String[] testKeywords = { "初吉丁亥", "王皮之子", "正月" };
//		String source = "王武征商隹唯甲子朝歲鼎克聞昏夙又有商辛未王才在柬閒闌次易賜又右事史檀公";
//		String[] testKeywords = { "武王", "商", "甲子" };
//		 String source =
//		 "連小利之於大者連小於曰利小者乍作心衣依余戉越者利大連者諸尸夷戉越禦曰隹唯余尸夷邾曰之乍作尸夷";
//		 String[] testKeywords = { "尸夷", "邾", "禦"};
//		 String source =
//		 "隹（唯）十又二年正月初吉丁亥，虢季子白乍（作）寶盤，不（丕）顯子白，爿由（壯）武于戎工（功），經維殳（維）四方，干尃（搏）伐允（玁狁），于洛之陽，折首五百，執訊五十，是（以）先行，走洛之陽，折首五百，執訊五十，是（以）先行，走（桓）走（桓）子白，獻聝（馘）于王，王孔加（嘉）子白義，王各周廟宣射（榭），爰鄉（饗），王曰：白父，孔日尹見又（有）光。王睗（賜）乘馬，是用左（佐）王，睗（賜）用弓、彤矢，其央；睗（賜）用戉（鉞），用政（征）（蠻）方，子子孫孫萬年無彊（疆）。";
//		 String[] testKeywords = { "丁亥", "虢季", "玁狁", "洛" };
		 
//		 String source =
//				 "楚王酓（熊）干心（悍）戰隻（獲）兵銅。正月吉日，臸（室）鑄喬（金喬）貞（鼎）之盍（蓋），（以）共（供）月（歲）尚示（嘗）。口二（冶）帀（師）卲糸差（佐）陳土（陳）共為之。";
//				 String[] testKeywords = { "酓熊", "楚王", "干心" };
		 
		List<String> selectedStr = new ArrayList<String>();
		for (int i = 0; i < testKeywords.length; i++) {
			selectedStr.add(testKeywords[i]);
		}

		List<String> srcDic = new ArrayList<String>();
		for (int i = 0; i < dictStr.length; i++) {
			for (int j = 0; j < dictStr[i].length; j++) {
				if (source.contains(dictStr[i][j])) {
					srcDic.add(dictStr[i][j]);
				}
			}
		}

		outputTreeForHeatMap(source,
				matchCharaFormDatabase(source, selectedStr, srcDic), selectedStr, srcDic);
		// outputInfoByJson(matchCharaFormDatabase(source, selectedStr));
	}

	public static void outputTreeForHeatMap(String source,
			List<InfoSource> dataLst, List<String> keywordLst, List<String> srcDic) {
		if (dataLst.size() == 0) {
			return;
		} else {
			String resultStr = "";
			resultStr += "day	hour	value\n";
			List<String> wordset = new ArrayList<String>();
			source = source.replaceAll("（", "").replaceAll("）", "")
					.replaceAll("／", "").replaceAll("，", "")
					.replaceAll("。", "");
			System.out.println(source);
			for (int i = 0; i < source.length(); i++) {
				if(!wordset.contains(source.substring(i, i + 1))){
					wordset.add(source.substring(i, i + 1));
				}
			}
			
			Integer[][] heatMap = new Integer[wordset.size()][dataLst.size()];
			for (int i = 0; i < wordset.size(); i++) {
				for (int j = 0; j < dataLst.size(); j++) {
					if (dataLst.get(j).content.contains(wordset.get(i))) {
						for (int j2 = 0; j2 < srcDic.size(); j2++) {
							if(srcDic.get(j2).contains(wordset.get(i))){
								heatMap[i][j] = 2;
								break;
							}
						}
						for (int j2 = 0; j2 < keywordLst.size(); j2++) {
							if(keywordLst.get(j2).contains(wordset.get(i))){
								heatMap[i][j] = 3;
								break;
							}
						}
						if(heatMap[i][j] == null || heatMap[i][j] < 0){
							heatMap[i][j] = 1;
						}
					}
					else{
						heatMap[i][j] = 0;
					}
				}
			}

			for (int ii = 0; ii < heatMap.length; ii++) {
				for (int i = 0; i < heatMap.length-ii-1; i++) {
					int sum = 0, sum2 = 0;

					for (int j = 0; j < heatMap[i].length; j++) {
						sum += heatMap[i][j];
						sum2 += heatMap[i + 1][j];
					}
					if (sum < sum2) {
						int tem = 0;
						for (int j = 0; j < heatMap[i].length; j++) {
							tem = heatMap[i][j];
							heatMap[i][j] = heatMap[i+1][j];
							heatMap[i+1][j] = tem;
						}
						String temStr = "";
						temStr = wordset.get(i);
						wordset.set(i, wordset.get(i+1));
						wordset.set(i+1, temStr);
					}
				}
			}
			String wordsStr = "var days = [";
			for (int i = 0; i < wordset.size(); i++) {
				wordsStr += "\""+wordset.get(i)+"\", ";
				System.out.print("\""+wordset.get(i)+"\", ");
			}
			wordsStr = wordsStr.substring(0, wordsStr.length()-2);
			wordsStr += "], \n times=[";
			for (int i = 0; i < dataLst.size(); i++) {
				String name = "";
				if(dataLst.get(i).srcType.equals("bronzes")){
					for (int j = 0; j < Constant.dataList.size(); j++) {
						if(Constant.dataList.get(j).get("sd_id").equals(""+dataLst.get(i).id)){
							name = ((String) Constant.dataList.get(j).get("sd_name")).split("（")[0];
						}
					}
				}else if(dataLst.get(i).srcType.equals("documents")){
					for (int j = 0; j < Constant.documentList.size(); j++) {
						if((""+Constant.documentList.get(j).get("doc_id")).contains(""+dataLst.get(i).id)){
							name = (String) Constant.documentList.get(j).get("doc_book");
						}
					}
				}
				wordsStr += "\""+name+"\", ";
			}
			wordsStr = wordsStr.substring(0, wordsStr.length()-2);
			wordsStr += "];";
			
			System.out.println(wordsStr);
			GenJsonJsFile.writeFile(outPutHeaAxisPath, wordsStr);
			for (int i = 0; i < heatMap.length; i++) {
				for (int j = 0; j < heatMap[i].length; j++) {
					if(heatMap[i][j] > 0){
						resultStr += (i + 1) + "	" + (j + 1) + "	" + heatMap[i][j]*10 + "\n";
					}
				}
			}
			System.out.println(resultStr);
			GenJsonJsFile.writeFile(outPutHeaPath, resultStr);


			List<Map<String, String>> nodeLst = new ArrayList<Map<String,String>>();
			List<Map<String, String>> linkLst = new ArrayList<Map<String,String>>();
			for (int i = 0; i < wordset.size(); i++) {
				boolean hit = false;
				for (int j2 = 0; j2 < keywordLst.size(); j2++) {
					if(keywordLst.get(j2).contains(wordset.get(i))){
						Map<String, String> newItem = new HashMap<String, String>();
						newItem.put("name", wordset.get(i));
						newItem.put("group", ""+3);
						nodeLst.add(newItem);
						hit = true;
						break;
					}
				}
				if(hit){
					continue;
				}
				for (int j2 = 0; j2 < srcDic.size(); j2++) {
					if(srcDic.get(j2).contains(wordset.get(i))){
						Map<String, String> newItem = new HashMap<String, String>();
						newItem.put("name", wordset.get(i));
						newItem.put("group", ""+8);
						nodeLst.add(newItem);
						hit = true;
						break;
					}
				}
				if(hit){
					continue;
				}
				Map<String, String> newItem = new HashMap<String, String>();
				newItem.put("name", wordset.get(i));
				newItem.put("group", ""+ 4);
				nodeLst.add(newItem);
			}
			
			int comNum = 0;
			for (int i = 0; i < nodeLst.size(); i++) {
				for (int j = i+1; j < nodeLst.size(); j++) {
					comNum = 0;
					for (int j2 = 0; j2 < dataLst.size(); j2++) {
						if(dataLst.get(j2).content.contains(nodeLst.get(i).get("name"))
								&& dataLst.get(j2).content.contains(nodeLst.get(j).get("name"))){
							comNum ++;
						}
					}
					if(comNum > 0){
						Map<String, String> newLink = new HashMap<String, String>();
						newLink.put("source", ""+i);
						newLink.put("target", ""+j);
						newLink.put("value", ""+(comNum));
						linkLst.add(newLink);
					}
				}
			}

			String matrixJsonStr = "{\"nodes\":[";
			for (int i = 0; i < nodeLst.size(); i++) {
				matrixJsonStr += "\n{\"name\":\""+nodeLst.get(i).get("name")+"\",\"group\":"+nodeLst.get(i).get("group")+"},";
			}
			matrixJsonStr = matrixJsonStr.substring(0,matrixJsonStr.length()-1);
			matrixJsonStr += "],\"links\":[";
			for (int i = 0; i < linkLst.size(); i++) {
				matrixJsonStr += "\n{\"source\":"+linkLst.get(i).get("source")+",\"target\":"+linkLst.get(i).get("target")+",\"value\":"+linkLst.get(i).get("value")+"},";
			}
			matrixJsonStr = matrixJsonStr.substring(0,matrixJsonStr.length()-1);
			matrixJsonStr += "]}";
			System.out.println(matrixJsonStr);
			GenJsonJsFile.writeFile(outPutCoorPath, matrixJsonStr);
		}
	}

	public static void outputTreeForSunburst(List<InfoSource> dataLst) {
		if (dataLst.size() == 0) {
			return;
		} else {
			List<String> wordset = new ArrayList<String>();
			wordset = dataLst.get(0).commonPart;
			for (int i = 0; i < dataLst.get(0).keywordsHit.size(); i++) {
				wordset.add(dataLst.get(0).keywordsHit.get(i));
			}

			for (int i = 0; i < wordset.size(); i++) {
				TreeNode newNode = new TreeNode(wordset.get(i));
				for (int j = 0; j < dataLst.size(); j++) {
					if (dataLst.get(j).commonPart.contains(wordset.get(i))
							|| dataLst.get(j).keywordsHit.contains(wordset
									.get(i))) {
						newNode.size++;
					}
				}
			}
		}

	}

	public static void outputInfoByJsHer(List<InfoSource> dataLst) {
		String resultStr = "";
		resultStr += "{ \"name\":\"keywords\", \"children\": [";
		for (int i = 0; i < dataLst.size(); i++) {
			resultStr += "\n{ \"name\":\"" + dataLst.get(i).id
					+ "\", \"children\":[";
			resultStr += "\n{ \"name\":\"commonPart\", \"children\":[";
			for (int j = 0; j < dataLst.get(i).commonPart.size(); j++) {
				resultStr += "\n{ \"name\":\""
						+ dataLst.get(i).commonPart.get(j)
						+ "\", \"size\":"
						+ (dataLst.get(i).matchLevel * dataLst.get(i).matchLevel)
						+ "},";
			}
			resultStr = resultStr.substring(0, resultStr.length() - 1);
			resultStr += "]},";

			resultStr += "\n{ \"name\":\"keywordsHit\", \"children\":[";
			for (int j = 0; j < dataLst.get(i).keywordsHit.size(); j++) {
				resultStr += "\n{ \"name\":\""
						+ dataLst.get(i).keywordsHit.get(j)
						+ "\", \"size\":"
						+ (dataLst.get(i).matchLevel * dataLst.get(i).matchLevel)
						+ "},";
			}
			resultStr = resultStr.substring(0, resultStr.length() - 1);
			resultStr += "]},";

			resultStr += "\n{ \"name\":\"dictHit\", \"children\":[";
			for (int j = 0; j < dataLst.get(i).dictHit.size(); j++) {
				resultStr += "\n{ \"name\":\""
						+ dataLst.get(i).dictHit.get(j)
						+ "\", \"size\":"
						+ (dataLst.get(i).matchLevel * dataLst.get(i).matchLevel)
						+ "},";
			}
			resultStr = resultStr.substring(0, resultStr.length() - 1);
			resultStr += "]}]},";
		}

		resultStr = resultStr.substring(0, resultStr.length() - 1);
		resultStr += "]}";
		// System.out.println(resultStr);
		GenJsonJsFile.writeFile(outPutHerPath, resultStr);
	}

	public static void outputInfoByJson(List<InfoSource> dataLst) {
		String resultStr = "";
		resultStr += "var hits = [";
		for (int i = 0; i < dataLst.size(); i++) {
			resultStr += "\n{\"id\":\"" + dataLst.get(i).id
					+ "\",\"content\":\"" + dataLst.get(i).content
					+ "\",\"srcType\":\"" + dataLst.get(i).srcType
					+ "\",\"commonPart\":[";
			for (int j = 0; j < dataLst.get(i).commonPart.size(); j++) {
				resultStr += "\"" + dataLst.get(i).commonPart.get(j) + "\",";
			}
			resultStr = resultStr.substring(0, resultStr.length() - 1)
					+ "],\"keywordsHit\":[";
			for (int j = 0; j < dataLst.get(i).keywordsHit.size(); j++) {
				resultStr += "\"" + dataLst.get(i).keywordsHit.get(j) + "\",";
			}
			resultStr = resultStr.substring(0, resultStr.length() - 1)
					+ "],\"dictHit\":[";
			for (int j = 0; j < dataLst.get(i).dictHit.size(); j++) {
				resultStr += "\"" + dataLst.get(i).dictHit.get(j) + "\",";
			}
			resultStr = resultStr.substring(0, resultStr.length() - 1) + "]},";
		}
		resultStr = resultStr.substring(0, resultStr.length() - 1) + "]";
		System.out.println(resultStr);
		GenJsonJsFile.writeFile(outPutPath, resultStr);
	}

	public static List<InfoSource> normalizeMultiData() {
		List<InfoSource> resultList = new ArrayList<InfoSource>();
		// 来自青铜器铭文的数据
		for (int i = 0; i < Constant.dataList.size(); i++) {
			InfoSource newItem = new InfoSource(Constant.dataList.get(i)
					.get("sd_content_explain").toString(), Constant.dataList
					.get(i).get("sd_id").toString(), "bronzes");
			resultList.add(newItem);
		}

		// 来自古文献的数据
		for (int i = 0; i < Constant.documentList.size(); i++) {
			InfoSource newItem = new InfoSource(Constant.documentList.get(i)
					.get("doc_content").toString(), Constant.documentList
					.get(i).get("doc_id").toString(), "documents");
			resultList.add(newItem);
		}
		// 来自其他来源的数据

		return resultList;
	}

	public static ArrayList<InfoSource> matchCharaFormDatabase(String source,
			List<String> keywords, List<String> dicsLst) {
		// 首先初始化数据
		List<InfoSource> textdataList = normalizeMultiData();
		source = source.replaceAll("（", "").replaceAll("）", "")
				.replaceAll("／", "").replaceAll("，", "").replaceAll("。", "");

		for (int i = 0; i < keywords.size(); i++) {
			keywords.get(i).replaceAll("（", "").replaceAll("）", "")
					.replaceAll("／", "");
		}

		List<InfoSource> resultInfoLst = new ArrayList<InfoSource>();
		// 计算整选定铭文和其他铭文的似度
		for (int i = 0; i < textdataList.size(); i++) {
			InfoSource thisItem = textdataList.get(i);
			String src = thisItem.content.replaceAll("（", "")
					.replaceAll("）", "").replaceAll("／", "");

			// 首先计算整体相似度
			thisItem.commonPart = compare(src, source);

			// 计算字典中的命中数
			for (int j = 0; j < keywords.size(); j++) {
				if (src.contains(keywords.get(j))) {
					if (!thisItem.keywordsHit.contains(keywords.get(j))) {
						thisItem.keywordsHit.add(keywords.get(j));
					}
				}
			}

			// 计算用户选定关键字的命中数
			for (int ii = 0; ii < dicsLst.size(); ii++) {
				if (source.contains(dicsLst.get(ii))
						&& !thisItem.dictHit.contains(dicsLst.get(ii))) {
					thisItem.dictHit.add(dicsLst.get(ii));
				}
			}
			List<String> temLst = new ArrayList<String>();
			boolean isIn;
			for (int j = 0; j < thisItem.commonPart.size(); j++) {
				if (thisItem.keywordsHit.size() == 0) {
					temLst = thisItem.commonPart;
					break;
				}
				isIn = false;
				for (int j2 = 0; j2 < thisItem.keywordsHit.size(); j2++) {
					if (thisItem.keywordsHit.get(j2).contains(
							thisItem.commonPart.get(j))
							|| temLst.contains(thisItem.commonPart.get(j))) {
						isIn = true;
					}
				}
				if (!isIn) {
					temLst.add(thisItem.commonPart.get(j));
				}
			}
			List<String> tem2Lst = new ArrayList<String>();
			for (int j = 0; j < temLst.size(); j++) {
				if (thisItem.dictHit.size() == 0) {
					tem2Lst = temLst;
					break;
				}
				isIn = false;
				for (int j2 = 0; j2 < thisItem.dictHit.size(); j2++) {
					if (thisItem.dictHit.get(j2).contains(temLst.get(j))
							|| tem2Lst.contains(temLst.get(j))) {
						isIn = true;
					}
				}

				if (!isIn) {
					tem2Lst.add(temLst.get(j));
				}
			}

			thisItem.commonPart = tem2Lst;

			thisItem.matchLevel = (double) ((double) thisItem.commonPart.size()
					/ source.length() + (double) thisItem.dictHit.size()
					/ dictStr.length + (double) thisItem.keywordsHit.size());

			if (thisItem.matchLevel > (double)(keywords.size()-thresPrecise)
					&& thisItem.keywordsHit.size() > 0) {
				resultInfoLst.add(thisItem);
			}
		}

		InfoSource temp;
		for (int i = 0; i < resultInfoLst.size(); i++) {
			for (int j = 0; j < resultInfoLst.size() - i - 1; j++) {
				if (resultInfoLst.get(j).matchLevel < resultInfoLst.get(j + 1).matchLevel) {
					temp = resultInfoLst.get(j);
					resultInfoLst.set(j, resultInfoLst.get(j + 1));
					resultInfoLst.set(j + 1, temp);
				}
			}
		}
		for (int i = 0; i < resultInfoLst.size(); i++) {
			InfoSource thisItem = resultInfoLst.get(i);
			System.out.println("\n------: " + thisItem.commonPart.size()
					+ "------: " + thisItem.dictHit.size() + "------: "
					+ thisItem.keywordsHit.size() + "------: "
					+ thisItem.matchLevel + "\n" + thisItem.content);
		}
		return (ArrayList<InfoSource>) resultInfoLst;
	}

	private static List<String> compare(String src, String tgt) {
		int tails = 2;
		List<String> resultLst = new ArrayList<String>();
		String matchStr = "";
		// for (int i = 0; i < tgt.length(); i++) {
		// if (src.contains(tgt.subSequence(i, i + 1))) {
		// if(i < tails){
		// matchStr = (String) tgt.subSequence(0, i + tails);
		// }else if(i > tgt.length() - tails){
		// matchStr = (String) tgt.subSequence(i-tails, tgt.length());
		// }else{
		// matchStr = (String) tgt.subSequence(i-tails, i + tails);
		// }
		// if (!resultLst.contains(matchStr)) {
		// resultLst.add((String) matchStr);
		// }
		// }
		// }

		for (int i = 0; i < tgt.length(); i++) {
			if (src.contains(tgt.subSequence(i, i + 1))) {
				matchStr = (String) tgt.subSequence(i, i + 1);
				if (!resultLst.contains(matchStr)) {
					resultLst.add((String) matchStr);
				}
			}
		}
		return resultLst;
	}
}
